package jupitermouse.site.licenseserver.service.impl;

import de.schlichtherle.license.*;
import jupitermouse.site.license.CustomKeyStoreParam;
import jupitermouse.site.license.CustomLicenseManager;
import jupitermouse.site.licenseserver.config.LicenseServerProperties;
import jupitermouse.site.licenseserver.controller.dto.CustomLicenseParam;
import jupitermouse.site.licenseserver.service.LicenseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.security.auth.x500.X500Principal;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Optional;
import java.util.prefs.Preferences;

/**
 * <p>
 * 许可证生成
 * </p>
 *
 * @author qiqiang.ren 2019/04/16 16:36
 */
@Service
@Slf4j
public class LicenseServiceImpl implements LicenseService {
    @Autowired
    private LicenseServerProperties properties;

    @Override
    public void generatorLicense(CustomLicenseParam param, HttpServletResponse response) {
        //设置对证书内容加密的秘钥
        LicenseManager licenseManager = new CustomLicenseManager(initLicenseParam(param));

        LicenseContent licenseContent = initLicenseContent(param);

        String defaultFileName = "license.lic";

        File file = Optional.ofNullable(properties.getServer().getLicensePath())
                .map(path -> {
                    File file1 = new File(path);
                    if (file1.exists()) {
                        file1.delete();
                    }
                    return file1;
                })
                .orElse(new File(properties.getLicenseParentDir() + "/" + System.currentTimeMillis() + "_" + defaultFileName));
        try {
            licenseManager.store(licenseContent, file);
        } catch (Exception e) {
            e.printStackTrace();
        }

        downLoadFile(file, defaultFileName, response);
    }

    private void downLoadFile(File file, String fileName, HttpServletResponse response) {
        // 配置文件下载
        response.setHeader("content-type", "application/octet-stream");
        response.setContentType("application/octet-stream");
        // 下载文件能正常显示中文
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

        // 实现文件下载
        byte[] buffer = new byte[1024];
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        try {
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            OutputStream os = response.getOutputStream();
            int i = bis.read(buffer);
            while (i != -1) {
                os.write(buffer, 0, i);
                i = bis.read(buffer);
            }
        } catch (Exception e) {
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private LicenseContent initLicenseContent(CustomLicenseParam param) {
        X500Principal DEFAULT_HOLDER_AND_ISSUER = new X500Principal(properties.getServer().getX500Principal());

        LicenseContent licenseContent = new LicenseContent();
        licenseContent.setHolder(DEFAULT_HOLDER_AND_ISSUER);
        licenseContent.setIssuer(DEFAULT_HOLDER_AND_ISSUER);
        licenseContent.setSubject(param.getSubject());
        licenseContent.setIssued(param.getIssuedTime());
        licenseContent.setNotBefore(param.getIssuedTime());
        licenseContent.setNotAfter(param.getExpiryTime());
        licenseContent.setConsumerType(properties.getServer().getConsumerType());
        licenseContent.setConsumerAmount(properties.getServer().getConsumerAmount());
        licenseContent.setInfo(properties.getServer().getDescription());
        //扩展校验服务器硬件信息
        licenseContent.setExtra(param.getExtra());

        return licenseContent;
    }

    private LicenseParam initLicenseParam(CustomLicenseParam param) {
        Preferences preferences = Preferences.userNodeForPackage(LicenseCreator.class);

        CipherParam cipherParam = new DefaultCipherParam(properties.getServer().getStorePass());
        KeyStoreParam privateStoreParam = new CustomKeyStoreParam(LicenseCreator.class
                , properties.getServer().getPrivateKeysStorePath()
                , properties.getServer().getPrivateAlias()
                , properties.getServer().getStorePass()
                , properties.getServer().getKeyPass());

        LicenseParam licenseParam = new DefaultLicenseParam(param.getSubject()
                , preferences
                , privateStoreParam
                , cipherParam);
        return licenseParam;
    }

}
